package wowplan.codegen; /**
 * Copyright © 2019 dream horse Info. Tech Ltd. All rights reserved.
 *
 * @Package: com.gitee.mybatis.fl.util
 * @author: flying-cattle
 * @date: 2019年4月9日 下午8:15:25
 */


import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.model.Server;
import common.GenTableColumn;
import wowplan.gen.model.GenTable;
import wowplan.gen.util.GenUtils;
import wowplan.gen.util.VelocityInitializer;
import wowplan.gen.util.VelocityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class EntityInfoUtil {

    public static String database = "iot";
//    public static String url = "jdbc:mysql://117.72.32.170:3306/" + database + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8";
//    public static String pass = "Zm123456!";

    public static String url = "jdbc:mysql://localhost:3306/" + database + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8";
    public static String name = "root";
    public static String pass = "zhouman123";


//	public static GenTable transferGenTable(GenTable param) {
//		String operName = "localRun";
//		GenTable genTable = null;
//		try {
//			String tableName = param.getTableName();
//			genTable = GenUtils.initClassNames(param, operName);
//			genTable.setTplCategory(GenConstants.TPL_CRUD); // 默认 crud
//
//			// 保存列信息
//			List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
//			for (GenTableColumn column : genTableColumns) {
//				GenUtils.initColumnField(column, genTable);
//			}
//			genTable.setColumns(genTableColumns);
//		} catch (Exception e) {
//			throw new CustomException("导入失败：" + e.getMessage());
//		}
//		return genTable;
//	}

    public static GenTable readTable(String tableName, String packageName, String tablePrefix) throws IOException {
//        Properties properties = PropertiesLoaderUtils.loadAllProperties("application-local.properties");
        // 创建连接
        Connection con = null;
        PreparedStatement pstemt = null;
        ResultSet rs = null;
        //sql
        // select table_name, table_comment, create_time, update_time from information_schema.tables
        //		where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
        //		and table_name = ''

        String sql = "select table_name, table_comment, create_time, update_time from information_schema.tables" +
                " where table_schema='" + database + "' and table_name='" + tableName + "'";
        try {
            GenTable genTable = null;
            con = DriverManager.getConnection(url, name, pass);
            pstemt = con.prepareStatement(sql);
            rs = pstemt.executeQuery();

            boolean autoRemovePre = true;

//            gen.author=ruoyi
//# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
//            gen.packageName=com.ruoyi.project.business
//# 自动去除表前缀，默认是true
//            gen.autoRemovePre=true
//# 表前缀（生成类名不会包含表前缀，多个用逗号分隔）
//            gen.tablePrefix=schedule_


            while (rs.next()) {
                genTable = new GenTable();
                String tableNameDB = rs.getString(1);
                String tableComment = rs.getString(2);
                Date createTime = rs.getDate(3);
                Date updateTime = rs.getDate(4);

                genTable.setTableName(tableName);
                genTable.setTableComment(tableComment);
                genTable.setTplCategory(GenConstants.TPL_CRUD); // 默认 crud


                GenUtils.initTable(genTable, "someone", packageName, autoRemovePre, tablePrefix);

                List<GenTableColumn> genTableColumns = readColumn(con, tableName);
                genTable.setColumns(genTableColumns);
                setPkColumn(genTable, genTableColumns);

            }
            if(genTable == null) {
                throw new RuntimeException("未获取到表信息");
            }

            // 完成后关闭
            rs.close();
            pstemt.close();
            con.close();
            return genTable;
        } catch (Exception e) {
            log.error("error sql: {}", sql, e);
            throw new RuntimeException("自动生成实体类错误：" + e.getMessage());
        } finally {
            try {
                if (rs != null) rs.close();
            } catch (SQLException se2) {
            }
            // 关闭资源
            try {
                if (pstemt != null) pstemt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (con != null) con.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }

    public static void setPkColumn(GenTable table, List<GenTableColumn> columns) {
        for (GenTableColumn column : columns) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtils.isNull(table.getPkColumn())) {
            table.setPkColumn(columns.get(0));
        }
    }


    public static List<GenTableColumn> readColumn(Connection con, String tableName) throws SQLException {
        List<GenTableColumn> columns = new ArrayList<>();
        // 创建连接
        PreparedStatement pstemt = null;
        ResultSet rs = null;
        //sql
        // select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
        //		from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
        //		order by ordinal_position
        String sql = "select column_name, " +
                "(case when (is_nullable = 'no' && column_key != 'PRI') then '1' else null end) as is_required, " +
                "(case when column_key = 'PRI' then '1' else '0' end) as is_pk, " +
                "ordinal_position as sort, " +
                "column_comment, " +
                "(case when extra = 'auto_increment' then '1' else '0' end) as is_increment, " +
                "column_type " +
                "from information_schema.columns where table_schema='" + database + "' and table_name='" + tableName + "' " +
                "order by ordinal_position";
        try {
            pstemt = con.prepareStatement(sql);
            rs = pstemt.executeQuery();
            while (rs.next()) {
                String columnName = rs.getString(1);
                String isRequired = rs.getString(2);
                String isPk = rs.getString(3);
                Integer sort = rs.getInt(4);
                String columnComment = rs.getString(5);
                String isIncrement = rs.getString(6);
                String columnType = rs.getString(7);

                GenTableColumn column = new GenTableColumn();
                column.setColumnName(columnName);
                column.setIsRequired(isRequired);
                column.setIsPk(isPk);
                column.setSort(sort);
                column.setColumnComment(columnComment);
                column.setIsIncrement(isIncrement);
                column.setColumnType(columnType);


                initColumnField(column);
                columns.add(column);
            }

            if (null == columns || columns.size() == 0) {
                throw new RuntimeException("未能读取到表或表中的字段。请检查链接url，数据库账户，数据库密码，查询的数据名、是否正确。");
            }
            return columns;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("自动生成实体类错误：" + e.getMessage());
        } finally {
            try {
                if (rs != null) rs.close();
            } catch (SQLException se2) {
            }
            // 关闭资源
            try {
                if (pstemt != null) pstemt.close();
            } catch (SQLException se2) {
            }// 什么都不做

        }
    }


    /**
     * 初始化列属性字段
     */
    public static void initColumnField(GenTableColumn column) {
        String dataType = GenUtils.getDbType(column.getColumnType());
        String columnName = column.getColumnName();
        // 设置java字段名
        column.setJavaField(StringUtils.toCamelCase(columnName));

        if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_STR, dataType)) {
            column.setJavaType(GenConstants.TYPE_STRING);
            // 字符串长度超过500设置为文本域
            Integer columnLength = GenUtils.getColumnLength(column.getColumnType());
            String htmlType = columnLength >= 500 ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
            column.setHtmlType(htmlType);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
            column.setJavaType(GenConstants.TYPE_TIME);
            column.setHtmlType(GenConstants.HTML_DATETIME);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_DATE_TIME, dataType)) {
            column.setJavaType(GenConstants.TYPE_DATE_TIME);
            column.setHtmlType(GenConstants.HTML_DATETIME);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_DATE, dataType)) {
            column.setJavaType(GenConstants.TYPE_DATE);
            column.setHtmlType(GenConstants.HTML_DATETIME);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_BIT, dataType)) {
            column.setJavaType(GenConstants.TYPE_BOOLEAN);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
            column.setHtmlType(GenConstants.HTML_INPUT);

            // 如果是浮点型 统一用BigDecimal
            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
            }
            // 如果是整形
            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
                column.setJavaType(GenConstants.TYPE_INTEGER);
            }
            // 长整形
            else {
                column.setJavaType(GenConstants.TYPE_LONG);
            }
        }

        // 插入字段（默认所有字段都需要插入）
        column.setIsInsert(GenConstants.REQUIRE);

        // 编辑字段
        if (!GenUtils.arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) {
            column.setIsEdit(GenConstants.REQUIRE);
        }
        // 列表字段
        if (!GenUtils.arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) {
            column.setIsList(GenConstants.REQUIRE);
        }
        // 查询字段
        if (!GenUtils.arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) {
            column.setIsQuery(GenConstants.REQUIRE);
        }

        // 查询字段类型
        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
            column.setQueryType(GenConstants.QUERY_LIKE);
        } else if (GenUtils.arraysContains(GenConstants.COLUMNNAME_EQ_TYPE, columnName) && !column.isPk()) {
            column.setQueryType(GenConstants.EQ);
        }
        // 状态字段设置单选框
        if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
            column.setHtmlType(GenConstants.HTML_RADIO);
        }
        // 类型&性别字段设置下拉框
        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
                || StringUtils.endsWithIgnoreCase(columnName, "sex")) {
            column.setHtmlType(GenConstants.HTML_SELECT);
        }
    }



    public static void generatorCodeToDisk(String tableName,
                                           String packageName, String tablePrefix) {

        GenTable table = null;
        try {
            table = EntityInfoUtil.readTable(tableName, packageName, tablePrefix);
        } catch (IOException e) {
            log.error("tableName 生成代码异常: " , e);
        }
        if(table == null) {
            throw new RuntimeException("读取表信息异常");
        }


        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);


        Server server = new Server();
        String osName = System.getProperty("os.name");


        String slash = "\\";
        if(StringUtils.containsIgnoreCase(osName, "mac")
                || StringUtils.containsIgnoreCase(osName, "linux")) {
            slash = "/";
        }

        String userDir = server.getUserDir().replace(slash + "ruoyi", "");
        String serverPorjectName = "ruoyi";
        String vuePorjectName = "ruoyi-ui";
        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            FileOutputStream fos = null;
            try {
                String fileName = userDir + slash + VelocityUtils.getFileNameToDisk(serverPorjectName, vuePorjectName, template, table);
                log.info("渲染模板 fileName {}", fileName);
//                String fileName = VelocityUtils.getFileNameToDisk(serverPorjectName, vuePorjectName, template, table);
                File file = new File(fileName);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                fos = new FileOutputStream(file);
                log.info("生成文件 ： {}", file.getAbsolutePath());
                IOUtils.write(sw.toString(), fos, Constants.UTF8);
                IOUtils.closeQuietly(sw);
            } catch (IOException e) {
                log.error("渲染模板失败，表名：{}, template: {}", table.getTableName(), template, e);
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        log.error("fos close failed", e);
                    }
                }
            }
        }
    }
}
